/**
 * G6流程图封装JS V0.0.2
 * 函数列表：
 *  1、init()  生成流程图
 *  2、update() 根据数据源刷新流程图
 *
 *  更新记录：
 *  2019-02-28 11:11
 * 使用说明：
 * cnpm install @antv/g6 --save
 */

import G6 from '@antv/g6';
import '@antv/g6/build/plugin.behaviour.analysis';
import '@antv/g6/build/plugin.layout.dagre';
import '@antv/g6/build/plugin.tool.tooltip';
import '@antv/g6/build/plugin.edge.polyline';
/**
 * 定义全局变量
 */
let graph;
let guideIndex=0;
/**
 *  通过数据绘制流程图
 *  默认缩放比根据图形尺寸自动判断
 * @param id 元素ID
 * @param width G6画布宽度
 * @param height G6画布高度
 * @param data G6绘图数据源
 * @returns {*}
 */
export function init(id,width, height,data) {

  //注册根节点（开始、结束）
  G6.registerNode('root', {
    intersectBox: 'rect',
    draw(item){
      const group = item.getGraphicGroup();
      let {name,radius} = item.getModel();
      if(!radius){
        radius=5;
      }
      const shape = root(group,0,0,radius);
      if(name){
        group.addShape('text', {
          attrs: {
            x: 30, // 居中
            y: 16,
            textAlign: 'center',
            textBaseline: 'middle',
            text: name,
            fill: 'black',
          }
        });
      }
      return shape;
    }
  });
  //注册处置节点
  G6.registerNode('node', {
    intersectBox: 'rect',
    draw(item) {
      const group = item.getGraphicGroup();
      let {name} = item.getModel();
      const shape = node(group,0,0,status);
      let text;
      if(name){
        text = group.addShape('text', {
          attrs: {
            x: 30, // 居中
            y: 16,
            textAlign: 'center',
            textBaseline: 'middle',
            text: name,
            fill: 'black',
          }
        });
      }
      return shape;
    }
  });

  const dagre = new G6.Layouts.Dagre();
  const tooltip = new G6.Plugins['tool.tooltip']();
  graph = new G6.Graph({
    container: id,
    width: width,
    height: height,
    fitView: 'autoZoom',
    modes: {
      default: ['panCanvas','wheelZoom']
    },
    layout: dagre,
    plugins: [ tooltip ]
  });
  graph.edge({
    shape: 'polyline'
  });
  graph.node({
    tooltip(model) {
      return [
        ['姓名', model.label]
      ]
    }
  });

  graph.read(data);
}

/**
 * 更新流程图数据
 * @param data G6绘图数据源
 */
export function update(data){
  guideIndex=0;
  //计算泳道
  //计算泳道宽高位置
  let minNode={},maxNode={};
  let nodes=data.nodes.sort((a,b)=>{return a.x-b.x});
  minNode.x=nodes[0].x;
  maxNode.x=nodes[nodes.length-1].x;
  nodes=data.nodes.sort((a,b)=>{return a.y-b.y});
  minNode.y=nodes[0].y;
  maxNode.y=nodes[nodes.length-1].y;
  if(data.guides){
    data.guides.forEach(item=>{
      if(item.shape==='states'){
        //注册状态说明
        G6.registerGuide('states', {
          draw(item) {
            let status=data.status;
            if(status !== undefined && status.length>0){
              const group = item.getGraphicGroup();
              let x1=maxNode.x+100,y1=minNode.y+guideIndex*50+10;
              group.addShape('text', {
                attrs: {
                  x:x1,
                  y:y1+10,
                  text:'图例说明：',
                  fill:'black',
                }
              });
              let t1=0;
              for(let i=0;i<status.length;i++){
                if(i%2===0){
                  group.addShape('circle', {
                    attrs: {
                      x:x1+10,
                      y:y1+t1*50+25,
                      r:5,
                      text:status[i].name,
                      fill:status[i].color,
                    }
                  });
                  group.addShape('text', {
                    attrs: {
                      x:x1+20,
                      y:y1+31+t1*50,
                      text:status[i].name,
                      fill:'black',
                    }
                  });
                }else{
                  group.addShape('circle', {
                    attrs: {
                      x:x1+90+status[i-1].name.length*4,
                      y:y1+t1*50+25,
                      r:5,
                      text:status[i].name,
                      fill:status[i].color,
                    }
                  });
                  group.addShape('text', {
                    attrs: {
                      x:x1+100+status[i-1].name.length*4,
                      y:y1+31+t1*50,
                      text:status[i].name,
                      fill:'black',
                    }
                  });
                  t1++;
                }
              }
              guideIndex+=t1;
            }
          }
        });
      }
      if(item.shape==='legend'){
        //注册图例说明
        G6.registerGuide('legend', {
          draw(item) {
            const group = item.getGraphicGroup();
            const {label} = item.getModel();
            if(label){
              let x1=maxNode.x+100,y1=minNode.y+guideIndex*5;
              group.addShape('text', {
                attrs: {
                  x:x1,
                  y:y1+guideIndex*50,
                  text:'图例说明：',
                  fill:'black',
                }
              });
              label.forEach(item=>{
                if(item.shape==='root'){
                  group.addShape('text', {
                    attrs: {
                      x:x1+70,
                      y:y1+32+guideIndex*50,
                      text:item.name,
                      fill:'black',
                    }
                  });
                  root(group,x1,y1+10+guideIndex*50,15);
                }else if(item.shape==='node'){
                  group.addShape('text', {
                    attrs: {
                      x:x1+70,
                      y:y1+32+guideIndex*50,
                      text:item.name,
                      fill:'black',
                    }
                  });
                  node(group,x1,y1+10+guideIndex*50,'black');
                }
                guideIndex++;
              });
            }



          }
        });
      }
    })
  }

  G6.registerGroup('lane', {
    draw(item) {
      const group = item.getGraphicGroup();
      let {label} = item.getModel();
      const childrenBox = item.getChildrenBBox();

      group.addShape('text', {
        attrs: {
          x:childrenBox.x+(childrenBox.width-label.length*12)/2,
          y:minNode.y-30,
          text: label,
          fill: 'black',
        }
      });
      group.addShape('rect', {
        attrs: {
          width:childrenBox.width+40,
          height:40,
          x:childrenBox.x-20,
          y:minNode.y-60,
          stroke:'black'
        }
      });
      return group.addShape('rect', {
        attrs: {
          width:childrenBox.width+40,
          height:maxNode.y-20,
          x:childrenBox.x-20,
          y:minNode.y-20,
          stroke: 'black',
        }
      });
    }
  });
  graph.read(data);
}

//----------以下为内部函数----------

/**
 * 通过圆的x坐标计算y坐标
 * @param r 半径长度
 * @param x x坐标
 * @returns {number}
 */
function circleMath(r,x) {
  //圆心公式(x-a)^2+(y-b)^2=r^2;
  return Math.sqrt(r * r - x * x);
}

/**
 * 绘制矩形节点
 * @param group G6 group对象
 * @param X 初始X坐标
 * @param Y 初始Y坐标
 * @returns {*}
 */
function node(group,X,Y) {
  let width=60,height=30;

  let path=drawRect(X,Y,width,height);
  return group.addShape('path', {
    attrs: {
      path:path,
      fill:'white',
      stroke: 'black' // 颜色应用到边上，如果应用到填充，则使用 fill
    }
  });
}

/**
 * 绘制圆角矩形节点
 * @param group G6 group对象
 * @param X 起始x坐标
 * @param Y G6 起始y坐标
 * @param radius 圆角半径范围
 * @returns {*}
 */
function root(group,X,Y,radius) {
  const width = 60;
  const height = 30;
  let path=[
    ['M', width/2+X, Y], // 上部顶点
    ['L', width-radius+X, Y], // 右侧点
  ];
  for (let i = 0;i<=radius;i++){
    let x,y;
    y=radius-circleMath(radius,i);
    x=width-radius+i;
    path.push(['L',x+X,y+Y]);
  }
  path.push(['L',width+X,height-radius+Y]);
  for (let i = radius;i>=0;i--){
    let x,y;
    y=height+circleMath(radius,i)-radius;
    x=width-radius+i;
    path.push(['L',x+X,y+Y]);
  }
  path.push(['L',radius+X,height+Y]);
  for (let i = 0;i>=-radius;i--){
    let x,y;
    y=height+circleMath(radius,i)-radius;
    x=i+radius;
    path.push(['L',x+X,y+Y]);
  }
  path.push(['L',X,radius+Y]);
  for (let i = -radius;i<=0;i++){
    let x,y;
    y=-circleMath(radius,i)+radius;
    x=i+radius;
    path.push(['L',x+X,y+Y]);
  }
  path.push(['Z']);

  return group.addShape('path', {
    attrs: {
      path:path,
      fill:'#FFCCCC',
      stroke: 'black' // 颜色应用到边上，如果应用到填充，则使用 fill: cfg.color
    }
  });
}

/**
 * 返回绘制矩形的Path
 * @param X 起始X坐标
 * @param Y 起始Y坐标
 * @param Width 矩形宽度
 * @param Height 矩形高度
 * @returns {*[]}
 */
function drawRect(X,Y,Width,Height) {
  return [
    ['M', X, Y],
    ['L', Width+X, Y],
    ['L', Width+X, Height+Y],
    ['L', X, Height+Y],
    ['Z']
  ];
}
